/**
    Adds the object jQuery.html, which contains a set of factory
    functions for generating new HTML elements. See the docs
    in the code below.


    Author: Stephan Beal (http://wanderinghorse.net/home/stephan/)

    License: Public Domain, unless your jQuery is licensed as GPL,
    in which case this code is necessarily GPL. (That's how viral
    licenses work!)
*/
jQuery.extend({
/**
An object containing a set of factory functions for generating new
HTML elements. It is intended to be used like this:

Old:

var x = jQuery("<span></span>");

New:

var x = jQuery.html.span();

It just looks nicer, not having all the HTML littering the code,
and it's less distracting in syntax-highlighted environments
(IMO), where the HTML strings have different colors than the
real code.
*/
html:
{
    /** Returns jQuery('<'+tag+'></'+tag+'>') */
    tag:function(tag) { return jQuery('<'+tag+'></'+tag+'>');},

    /* Headers and separators. */
    hN:function(n) { return this.tag('h'+n);},
    h1:function(n) { return this.hN(1);},
    h2:function(n) { return this.hN(2);},
    h3:function(n) { return this.hN(3);},
    br:function() { return jQuery('<br/>'); },
    hr:function() { return jQuery('<hr/>'); },
    nbsp:function() { return this.span().append('&nbsp;'); },

    /* Blocks/containers. */
    div:function() { return this.tag('div');},
    p:function() { return this.tag('p');},
    pre:function() { return this.tag('pre');},
    blockquote:function() { return this.tag('blockquote');},
    iframe:function(){ return jQuery("<iframe src='about:blank'/>"); },

    /* General text formatting. */
    span:function() { return this.tag('span');},
    tt:function() { return this.tag('tt');},
    b:function() { return this.tag('b');},
    strong:function() { return this.tag('strong');},
    em:function() { return this.tag('em');},
    i:function() { return this.tag('i');},
    strike:function() { return this.tag('strike');},
    u:function() { return this.tag('u');},
    sup:function() { return this.tag('sup');},
    sub:function() { return this.tag('sub');},

    /* Tables */
    /* table() returns a table with a tbody. Some browsers automatically create
    a tbody entry if not is specified, some do not. Some might allow creation
    of a standalone tbody to insert into a table, whereas others might not.
    So... we just create it all together.
    */
    td:function() { return this.tag('td');},
    th:function() { return this.tag('th');},
    thead:function() { return this.tag('thead');},
    /**
        Returns a new jQuery TR object with member functions
        td() and th(), each of which creates a new TD resp. TH
        jQuery object, appends it to this TR element, and returns it.
    */
    tr:function()
    {
        var tr = this.tag('tr');
        var self = this;
        var td = arguments.callee.td;
        if( ! td )
        {
            td = arguments.callee.td = function td()
            {
                return self.td().appendTo(self);
            };
        }
        var th = arguments.callee.th;
        if( !th )
        {
            th = arguments.callee.th = function th()
            {
                return self.th().appendTo(self);
            };
        }
        tr.td = td;
        tr.th = th;
        return tr;
    },
    /**
        Returns a new jQuery TABLE object with a member function
        tr() which creates a new row, appends to the TABLE,
        and returns it.

        The header and body elements are available via the
        thead and tbody properties, which are jQuery objects
        wrapping their appropriate elements.
    */
    table:function()
    {
        var tbl = jQuery('<table><thead></thead><tbody></tbody></table>');
        var self = this;
        var tr = arguments.callee.tr;
        if( ! tr )
        {
            tr = arguments.callee.tr = function tr()
            {
                var x = self.tr();
                x.appendTo(self);
                return x;
            };
        }
//         var thead = arguments.callee.thead;
//         if( ! thead )
//         {
//             thead = arguments.callee.thead = function thead()
//             {
//                 return jQuery('thead',this);
//             };
//         }
//         var tbody = arguments.callee.tbody;
//         if( ! tbody )
//         {
//             tbody = arguments.callee.tbody = function tbody()
//             {
//                 return jQuery('tbody',this);
//             };
//         }
        tbl.thead = jQuery('thead',tbl);
        tbl.tbody = jQuery('tbody',tbl);
        tbl.tr = tr;
        return tbl;
    },

    /* Lists: */
    li:function(n) { return this.tag('li');},
    /**
        Returns a new jQuery UL object with a member function
        li() which creates a new LI element, appends to the UL,
        and returns it.
    */
    ul:function(n)
    {
        var l = this.tag('ul');
        var self = this;
        var li = arguments.callee.li;
        if( ! li )
        {
            li = arguments.callee.li = function li()
            {
                return self.li().appendTo(this);
            };
        }
        l.li = li;
        return l;
    },
    /**
        Returns a new jQuery OL object with a member function
        li() which creates a new LI element, appends to the OL,
        and returns it.
    */
    ol:function(n)
    {
        var l = this.tag('ol');
        var self = this;
        var li = arguments.callee.li;
        if( ! li )
        {
            li = arguments.callee.li = function li()
            {
                return self.li().appendTo(this);
            };
        }
        l.li = li;
        return l;
    },

    /* Input */
    form:function() { return this.tag('form'); },
    input:function(inputType) { return jQuery("<input type='"+inputType+"'></input>"); },
    button:function() { return this.input('button');},
    /* i just couldn't bring myself to call this text(). */
    textfield:function() { return this.input('text');},
    checkbox:function() { return this.input('checkbox');},
    radio:function() { return this.input('radio');},
    hidden:function() { return this.input('hidden');},
    /**
        Returns a new jQuery SELECT object with a member function
        option() which creates a new option element, appends to the
        SELECT, and returns it.
    */
    select:function()
    {
        var sel = this.tag('select');
        var self = this;
        var option = arguments.callee.option;
        if( ! option )
        {
            option = arguments.callee.option = function option()
            {
                return self.option().appendTo(this);
            };
        }
        sel.option = option;
        return sel;
    },
    option:function() { return this.tag('option');},
    textarea:function() { return this.tag('textarea');},
    fieldset:function() { return this.tag('fieldset');},

    /** Misc. */
    img:function() { return this.tag('img');},
    /* Returns a link with href='#'. */
    a:function() {
        //function _false() { return false; };
        return this.tag('a').attr('href','#')
            //.click(_false)
            ;
    }
}/*html*/
});
